
<!--
current: 当前页码，类型为 Number，默认为 1。用于控制当前显示的页码。
totalPage: 总页数，类型为 Number 或 String，必填。用于控制分页的总页数。
totalItems: 总条数，类型为 Number，必填。表示数据的总记录数。
size: 每页显示的记录数，类型为 Number，默认为 10。用于控制每页显示的记录数量。
sizeOptions: 每页记录数的可选项，类型为 Array<Number>，默认为 [10, 20, 30, 50]。定义用户可以选择的每页记录数。
theme: 主题风格，类型为 String，默认为 light。设置分页组件的主题风格，支持 light 和 dark。
color: 组件的主色调，类型为 String，默认为 #1890ff。设置分页组件的主色调，影响按钮的边框和背景颜色。
showQuickJumper: 是否显示跳转页码输入框，类型为 Boolean，默认为 true。控制是否显示跳转页码的输入框。
showSizePicker: 是否显示每页记录数选择器，类型为 Boolean，默认为 true。控制是否显示每页记录数的选择器。
visiblePagesCount: 显示的页码按钮数量，类型为 Number，默认为 5。控制显示在分页组件上的页码按钮数量。
-->
<template>
  <div :class="['sg-pagination', themeClass]" :style="colorStyle">
    <div class="sg-pagination-info">
      <span>共 {{ totalPage }} 页</span>
      <span>共 {{ totalItems }} 条记录</span>
    </div>

    <button
      class="sg-pagination-button"
      :disabled="currentPage === 1"
      @click="changePage(currentPage - 1)"
    >
      上一页
    </button>

    <button
      v-for="p in visiblePages"
      :key="p"
      :class="['sg-pagination-button', { 'active': p === currentPage }]"
      @click="changePage(p)"
    >
      {{ p }}
    </button>

    <button
      class="sg-pagination-button"
      :disabled="currentPage === totalPage"
      @click="changePage(currentPage + 1)"
    >
      下一页
    </button>

    <select v-if="showSizePicker" v-model="pageSize" @change="updatePageSize">
      <option v-for="size in sizeOptions" :key="size" :value="size">{{ size }} 条/页</option>
    </select>

    <input
      v-if="showQuickJumper"
      type="number"
      v-model.number="jumpPage"
      @keyup.enter="changePage(jumpPage)"
      placeholder="跳转页码"
    />
  </div>
</template>

<script lang="ts">
import { defineComponent, ref, computed, watch } from 'vue';

export default defineComponent({
  name: 'SgPagination',
  props: {
    current: { // currentPage
      type: Number,
      default: 1,
    },
    totalPage: { // pageCount
      type: [Number, String],
      required: true,
      validator(value) {
        return !isNaN(Number(value)); // 确保可以转换为数字
      }
    },
    totalItems: { // 新增 totalItems 表示总条数
      type: Number,
      required: true,
    },
    size: { // pageSize
      type: Number,
      default: 10,
    },
    sizeOptions: { // pageSizes
      type: Array,
      default: () => [10, 20, 30, 50],
    },
    theme: {
      type: String,
      default: 'light',
    },
    color: {
      type: String,
      default: '#1890ff',
    },
    showQuickJumper: {
      type: Boolean,
      default: true,
    },
    showSizePicker: {
      type: Boolean,
      default: true,
    },
    visiblePagesCount: {
      type: Number,
      default: 5,
    },
  },
  setup(props, { emit }) {
    const currentPage = ref(Number(props.current));
    const pageSize = ref(props.size);
    const jumpPage = ref(Number(props.current));

    // 初始化时同步内部状态
    watch(
      () => props.current,
      (newPage) => {
        const pageNum = Number(newPage);
        if (pageNum !== currentPage.value) {
          currentPage.value = pageNum;
          jumpPage.value = pageNum;
        }
      },
      { immediate: true }
    );

    const themeClass = computed(() => {
      return props.theme === 'dark' ? 'sg-pagination-dark' : 'sg-pagination-light';
    });

    const colorStyle = computed(() => {
      return {
        '--sg-pagination-color': props.color,
      };
    });

    const visiblePages = computed(() => {
      const half = Math.floor(props.visiblePagesCount / 2);
      const totalPageNum = Number(props.totalPage);
      let start = Math.max(1, currentPage.value - half);
      let end = Math.min(totalPageNum, start + props.visiblePagesCount - 1);

      if (end - start < props.visiblePagesCount - 1) {
        start = Math.max(1, end - props.visiblePagesCount + 1);
      }
      return Array.from({ length: end - start + 1 }, (_, i) => start + i);
    });

    const changePage = (page: number) => {
      const totalPageNum = Number(props.totalPage);
      if (page < 1 || page > totalPageNum) return;
      currentPage.value = page;
      jumpPage.value = page;
      emit('update:current', page);
      emit('page-change', page);
    };

    const updatePageSize = () => {
      emit('update:size', pageSize.value);
      emit('page-size-change', pageSize.value);
      changePage(1); // 重置到第一页
    };

    return {
      currentPage,
      pageSize,
      jumpPage,
      themeClass,
      colorStyle,
      visiblePages,
      changePage,
      updatePageSize,
    };
  },
});
</script>

<style scoped>
.sg-pagination {
  display: flex;
  align-items: center;
  gap: 5px;
  padding: 10px;
}

.sg-pagination-info {
  margin-right: auto;
  display: flex;
  gap: 10px;
  font-size: 14px;
  color: #666;
}

.sg-pagination-button {
  border: 1px solid var(--sg-pagination-color, #1890ff);
  background-color: transparent;
  color: var(--sg-pagination-color, #1890ff);
  padding: 5px 10px;
  cursor: pointer;
  border-radius: 4px;
}

.sg-pagination-button:disabled {
  cursor: not-allowed;
  opacity: 0.5;
}

.sg-pagination-button.active {
  background-color: var(--sg-pagination-color, #1890ff);
  color: #fff;
}

.sg-pagination-light {
  background-color: #fff;
  color: #000;
}

.sg-pagination-dark {
  background-color: #333;
  color: #fff;
}

select, input {
  margin-left: 10px;
  padding: 5px;
  border: 1px solid #ccc;
  border-radius: 4px;
}

input {
  width: 60px;
  text-align: center;
}
</style>
